<!-- https://codepen.io/jkantner/pen/YzLQoXM -->
<html lang="en">

<head>

  <meta charset="UTF-8">

  <link rel="apple-touch-icon" type="image/png"
    href="https://cpwebassets.codepen.io/assets/favicon/apple-touch-icon-5ae1a0698dcc2402e9712f7d01ed509a57814f994c660df9f7a952f3060705ee.png">
  <meta name="apple-mobile-web-app-title" content="CodePen">

  <link rel="shortcut icon" type="image/x-icon"
    href="https://cpwebassets.codepen.io/assets/favicon/favicon-aec34940fbc1a6e787974dcd360f2c6b63348d4b1f4e06c77743096d55480f33.ico">

  <link rel="mask-icon" type="image/x-icon"
    href="https://cpwebassets.codepen.io/assets/favicon/logo-pin-8f3771b1072e3c38bd662872f6b673a722f4b3ca2421637d5596661b4e2132cc.svg"
    color="#111">


  <title>CodePen - Changing Face Rating</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">

  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=DM+Sans&amp;display=swap">

  <style>
    * {
      border: 0;
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }

    :root {
      --hue: 223;
      --white: hsl(var(--hue), 10%, 100%);
      --lt-gray: hsl(var(--hue), 10%, 95%);
      --gray1: hsl(var(--hue), 10%, 90%);
      --gray2: hsl(var(--hue), 10%, 80%);
      --gray7: hsl(var(--hue), 10%, 30%);
      --gray9: hsl(var(--hue), 10%, 10%);
      --primary: hsl(var(--hue), 90%, 55%);
      --trans-dur: 0.3s;
      font-size: calc(16px + (24 - 16) * (100vw - 320px) / (1280 - 320));
    }

    body,
    input {
      font: 1em/1.5 "DM Sans", sans-serif;
    }

    body {
      background-color: var(--white);
      color: var(--gray9);
      height: 100vh;
      display: grid;
      place-items: center;
      transition:
        background-color var(--trans-dur),
        color var(--trans-dur);
    }

    /* Main styles */
    .fr {
      animation: fade-slide-in 0.6s ease-out;
      padding: 0 1.5em;
      max-width: 20em;
    }

    .fr__face {
      --face-hue1: 60;
      --face-hue2: 30;
      background-image:
        linear-gradient(135deg,
          hsl(var(--face-hue1), 90%, 55%),
          hsl(var(--face-hue2), 90%, 45%));
      border-radius: 50%;
      box-shadow: 0 0.5em 0.75em hsla(var(--face-hue2), 90%, 55%, 0.3);
      margin: 0 auto 2em;
      position: relative;
      width: 3em;
      height: 3em;
    }

    .fr__face-right-eye,
    .fr__face-left-eye,
    .fr__face-mouth-lower,
    .fr__face-mouth-upper {
      position: absolute;
      transition:
        background-color var(--trans-dur),
        box-shadow var(--trans-dur),
        color var(--trans-dur);
    }

    .fr__face-right-eye,
    .fr__face-left-eye {
      background-color: var(--white);
      border-radius: 50%;
      top: 0.75em;
      width: 0.6em;
      height: 0.6em;
    }

    .fr__face-right-eye {
      --delay-right: 0s;
      animation: right-eye 1s var(--delay-right) linear paused;
      clip-path: polygon(0 75%, 100% 0, 100% 100%, 0 100%);
      left: 0.6em;
    }

    .fr__face-left-eye {
      --delay-left: 0s;
      animation: left-eye 1s var(--delay-left) linear paused;
      clip-path: polygon(0 0, 100% 75%, 100% 100%, 0 100%);
      right: 0.6em;
    }

    .fr__face-mouth-lower,
    .fr__face-mouth-upper {
      color: var(--white);
      top: 1.75em;
      left: 0.75em;
      width: 1.5em;
      height: 0.75em;
    }

    .fr__face-mouth-lower {
      --delay-mouth-lower: 0s;
      animation: mouth-lower 1s var(--delay-mouth-lower) linear paused;
      border-radius: 50% 50% 0 0 / 100% 100% 0 0;
      box-shadow: 0 0.125em 0 inset;
    }

    .fr__face-mouth-upper {
      --delay-mouth-upper: 0s;
      animation: mouth-upper 1s var(--delay-mouth-upper) linear paused;
      border-radius: 0 0 50% 50% / 0 0 100% 100%;
      box-shadow: 0 -0.125em 0 inset;
    }

    .fr__label {
      display: block;
      margin-bottom: 1.5em;
      text-align: center;
    }

    .fr__input {
      --input-hue: 60;
      --percent: 50%;
      background-color: var(--gray1);
      background-image: linear-gradient(hsl(var(--input-hue), 90%, 45%), hsl(var(--input-hue), 90%, 45%));
      background-size: var(--percent) 100%;
      background-repeat: no-repeat;
      border-radius: 0.25em;
      display: block;
      margin: 0.5em auto;
      width: 100%;
      max-width: 10em;
      height: 0.5em;
      transition: background-color var(--trans-dur);
      -webkit-appearance: none;
      appearance: none;
      -webkit-tap-highlight-color: transparent;
    }

    .fr__input:focus {
      outline: transparent;
    }

    /* WebKit */
    .fr__input::-webkit-slider-thumb {
      background-color: var(--white);
      border: 0;
      border-radius: 50%;
      box-shadow: 0 0.125em 0.5em hsl(0, 0%, 0%, 0.3);
      width: 1.5em;
      height: 1.5em;
      transition: background-color 0.15s linear;
      -webkit-appearance: none;
      appearance: none;
    }

    .fr__input:focus::-webkit-slider-thumb,
    .fr__input::-webkit-slider-thumb:hover {
      background-color: var(--lt-gray);
    }

    /* Firefox */
    .fr__input::-moz-range-thumb {
      background-color: var(--white);
      border: 0;
      border-radius: 50%;
      box-shadow: 0 0.125em 0.5em hsl(0, 0%, 0%, 0.3);
      width: 1.5em;
      height: 1.5em;
      transition: background-color 0.15s linear;
    }

    .fr__input:focus::-moz-range-thumb,
    .fr__input::-moz-range-thumb:hover {
      background-color: var(--lt-gray);
    }

    /* `:focus-visible` support */
    @supports selector(:focus-visible) {
      .fr__input:focus::-webkit-slider-thumb {
        background-color: var(--white);
      }

      .fr__input:focus-visible::-webkit-slider-thumb,
      .fr__input::-webkit-slider-thumb:hover {
        background-color: var(--lt-gray);
      }

      .fr__input:focus::-moz-range-thumb {
        background-color: var(--white);
      }

      .fr__input:focus-visible::-moz-range-thumb,
      .fr__input::-moz-range-thumb:hover {
        background-color: var(--lt-gray);
      }
    }

    /* Dark theme */
    @media (prefers-color-scheme: dark) {
      body {
        background-color: var(--gray9);
        color: var(--gray1);
      }

      .fr__face-right-eye,
      .fr__face-left-eye {
        background-color: var(--gray9);
      }

      .fr__face-mouth-lower,
      .fr__face-mouth-upper {
        color: var(--gray9);
      }

      .fr__input {
        background-color: var(--gray7);
      }
    }

    /* Animations */
    @keyframes fade-slide-in {

      from,
      16.67% {
        opacity: 0;
        transform: translateY(25%);
      }

      to {
        opacity: 1;
        transform: translateY(0);
      }
    }

    @keyframes right-eye {
      from {
        clip-path: polygon(0 75%, 100% 0, 100% 100%, 0 100%);
      }

      50%,
      to {
        clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
      }
    }

    @keyframes left-eye {
      from {
        clip-path: polygon(0 0, 100% 75%, 100% 100%, 0 100%);
      }

      50%,
      to {
        clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
      }
    }

    @keyframes mouth-lower {
      from {
        border-radius: 50% 50% 0 0 / 100% 100% 0 0;
        top: 1.75em;
        height: 0.75em;
        visibility: visible;
      }

      40% {
        border-radius: 50% 50% 0 0 / 100% 100% 0 0;
        top: 1.95em;
        height: 0.25em;
        visibility: visible;
      }

      50%,
      to {
        border-radius: 0;
        top: 2em;
        height: 0.125em;
        visibility: hidden;
      }
    }

    @keyframes mouth-upper {

      from,
      50% {
        border-radius: 0;
        box-shadow: 0 -0.125em 0 inset;
        top: 2em;
        height: 0.125em;
        visibility: hidden;
      }

      62.5% {
        border-radius: 0 0 50% 50% / 0 0 100% 100%;
        box-shadow: 0 -0.125em 0 inset;
        top: 1.95em;
        height: 0.25em;
        visibility: visible;
      }

      75% {
        border-radius: 0 0 50% 50% / 0 0 100% 100%;
        box-shadow: 0 -0.125em 0 inset;
        top: 1.825em;
        height: 0.5em;
        visibility: visible;
      }

      to {
        border-radius: 0 0 50% 50% / 0 0 100% 100%;
        box-shadow: 0 -0.8em 0 inset;
        top: 1.75em;
        height: 0.75em;
        visibility: visible;
      }
    }
  </style>

  <script>
    window.console = window.console || function (t) { };
  </script>



  <script>
    if (document.location.search.match(/type=embed/gi)) {
      window.parent.postMessage("resize", "*");
    }
  </script>


  <input type="hidden" id="_w_simile" data-inspect-config="3">
  <script type="text/javascript"
    src="chrome-extension://odphnbhiddhdpoccbialllejaajemdio/scripts/inspector.js"></script>
</head>

<body translate="no">
  <form class="fr" action="">
    <label class="fr__label" for="face-rating">How was your experience?</label>
    <div class="fr__face" role="img" aria-label="Sad face" style="--face-hue1:0; --face-hue2:330;">
      <div class="fr__face-right-eye" data-right="" style="--delay-right:0s;"></div>
      <div class="fr__face-left-eye" data-left="" style="--delay-left:0s;"></div>
      <div class="fr__face-mouth-lower" data-mouth-lower="" style="--delay-mouth-lower:0s;"></div>
      <div class="fr__face-mouth-upper" data-mouth-upper="" style="--delay-mouth-upper:0s;"></div>
    </div>
    <input class="fr__input" id="face-rating" type="range" value="2.5" min="0" max="5" step="0.1"
      style="--percent:0%; --input-hue:0;">
  </form>
  <script
    src="https://cpwebassets.codepen.io/assets/common/stopExecutionOnTimeout-2c7831bb44f98c1391d6a4ffda0e1fd302503391ca806e7fcc7b9b87197aec26.js"></script>


  <script id="rendered-js">
    window.addEventListener("DOMContentLoaded", () => {
      const fr = new FaceRating("#face-rating");
    });

    class FaceRating {
      constructor(qs) {
        this.input = document.querySelector(qs);
        this.input?.addEventListener("input", this.update.bind(this));
        this.face = this.input?.previousElementSibling;
        this.update();
      }
      update(e) {
        let value = this.input.defaultValue;

        // when manually set
        if (e) value = e.target?.value;
        // when initiated
        else this.input.value = value;

        const min = this.input.min || 0;
        const max = this.input.max || 100;
        const percentRaw = (value - min) / (max - min) * 100;
        const percent = +percentRaw.toFixed(2);

        this.input?.style.setProperty("--percent", `${percent}%`);

        // face and range fill colors
        const maxHue = 120;
        const hueExtend = 30;
        const hue = Math.round(maxHue * percent / 100);

        let hue2 = hue - hueExtend;
        if (hue2 < 0) hue2 += 360;

        const hues = [hue, hue2];
        hues.forEach((h, i) => {
          this.face?.style.setProperty(`--face-hue${i + 1}`, h);
        });

        this.input?.style.setProperty("--input-hue", hue);

        // emotions
        const duration = 1;
        const delay = -(duration * 0.99) * percent / 100;
        const parts = ["right", "left", "mouth-lower", "mouth-upper"];

        parts.forEach(p => {
          const el = this.face?.querySelector(`[data-${p}]`);
          el?.style.setProperty(`--delay-${p}`, `${delay}s`);
        });

        // aria label
        const faces = [
          "Sad face",
          "Slightly sad face",
          "Straight face",
          "Slightly happy face",
          "Happy face"];

        let faceIndex = Math.floor(faces.length * percent / 100);
        if (faceIndex === faces.length) --faceIndex;

        this.face?.setAttribute("aria-label", faces[faceIndex]);
      }
    }
//# sourceURL=pen.js
  </script>







</body>

</html>